home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 288_01.zip / MSTR_ENV.TXT < prev    next >
Text File  |  1993-04-01  |  11KB  |  217 lines

  1.                                              Scott Robert Ladd
  2.                                              302 North 12th St.
  3.                                              Gunnison, CO 81230
  4.                                              (303) 641-6438
  5.  
  6.                                              1700 words
  7.                                               350 source lines
  8.  
  9.  
  10.                 Accessing the Master Environment in MS-DOS
  11.                            by Scott Robert Ladd
  12.  
  13.      When writing software for MS-DOS, a programmer often 
  14. confronts what seem to be artificial restrictions on what can and 
  15. can't be done. Some of the utilities provided with MS-DOS can 
  16. accomplish tasks which the programmer cannot duplicate through 
  17. documented features of the operating system. This article 
  18. attempts to lift the shroud from one of MS-DOS's hidden secrets 
  19. by providing functions for accessing the master copy of the MS-
  20. DOS environment. It is assumed that the reader is familiar with 
  21. the 8088's segmented memory model and the way in which MS-DOS 
  22. functions are accessed via software interrupts.
  23.  
  24.      The environment is a collection of text variables maintained 
  25. by COMMAND.COM. These variables consist of a name and an 
  26. associated text string. Environment variables are used for a wide 
  27. variety of purposes by both the operating system and application 
  28. programs. Common examples of environment variables include 
  29. COMSPEC (which stores the pathname of the MS-DOS shell), PROMPT 
  30. (the prompt definition string), and PATH (containing the list of 
  31. directories to be searched for executable files). Some 
  32. environment variables are maintain through special commands, as 
  33. in the preceding examples. Other environment variables are stored 
  34. using the internal MS-DOS command SET. Programmers are well aware 
  35. of environment variables; most compilers use them for locating 
  36. header files, libraries, and compiler components.
  37.  
  38.      Every program in MS-DOS has its own environment. A program 
  39. which executes another program is known as a "parent", while the 
  40. program it executed is called a "child". A child, in turn, can 
  41. also be the parent of other programs. A child process inherits a 
  42. copy of the environment associated with its parent. Changes made 
  43. by the child to its copy of the environment have no affect on the 
  44. parent's copy -- and vice versa.
  45.  
  46.      The MS-DOS command shell, COMMAND.COM, is the ultimate 
  47. parent of all resident programs, since it is the first program 
  48. loaded. At boot time, COMMAND.COM allocates a block of memory 
  49. into which it stores the master environment variables. Since most 
  50. programs are executed from the COMMAND.COM prompt, it is the 
  51. direct parent of most programs. However, many programs are 
  52. capable of running other programs directly, and additional copies 
  53. of COMMAND.COM can be resident simultaneously as well.
  54.  
  55.      When a program is loaded by MS-DOS, a 256-byte header is 
  56. created for it. This header contains important operating system 
  57. data, and is called the Program Segment Prefix (PSP). A program 
  58. can locate the copy of its local environment via a segment 
  59. pointer stored at offset 0x2C within the PSP. Most MS-DOS 
  60. implementations of C provide the function getenv(), which 
  61. retrieves the value of an environment variable from the local 
  62. environment. Some compilers also offer a putenv() function, which 
  63. stores a variable in the local environment.
  64.  
  65.      Putenv() is not particularly useful. When a local 
  66. environment is created, it's size is only slightly larger than 
  67. that required to hold all of the existing variables in the parent 
  68. environment. A copy of the environment cannot be expanded, so 
  69. there is very little room to add new variables. Any changes to a 
  70. local environment are transient; when a program terminates, its 
  71. local environment vanishes too. In addition, changing the local 
  72. copy of the environment is solely useful if child programs are to 
  73. be executed, since they are the only ones which will see new or 
  74. changed values. 
  75.  
  76.      It would be useful to make changes to the master 
  77. environment. A program could pass along information to other 
  78. programs through master environment variables. A program could 
  79. store status information for future incarnations of itself in the 
  80. master environment. A TSR can use the variables in the global 
  81. environment to ensure that it is aware of any changes since it 
  82. was executed. The problem is that MS-DOS does not provide any 
  83. documented way of accessing the master environment. In order to 
  84. work with the master environment, we must enter the world of 
  85. undocumented features. I'll begin with a short discussion of MS-
  86. DOS memory management.
  87.  
  88.      MS-DOS organizes memory into blocks. Each block is prefaced 
  89. by a 16-byte paragraph-aligned header called the Memory Control 
  90. Block, or MCB for short. The MCB contains 3 pieces of 
  91. information: a status indicator, the segment of the owning 
  92. program's PSP, and the length of the block. The status indicator 
  93. is a byte which contains either the character 'M' (indicating 
  94. that it is a member of the MCB chain) or a 'Z' (denoting this as 
  95. the last MCB in the chain). The length of the block is stored as 
  96. a number of 16-byte paragraphs.
  97.  
  98.      Many popular public domain programs can use the chain of 
  99. MCBs to display a map of programs and data resident in memory. 
  100. The first MCB can be located through an undocumented INT 0x21 
  101. service of MS-DOS, 0x52. Function 0x52 returns a pointer (in 
  102. ES:BX) to an internal table of MS-DOS values. Immediately 
  103. preceding this table is the segment address of the first MCB. 
  104. Starting with the first MCB, a program can follow the chain of 
  105. memory blocks by a simple formula: add the size of a block plus 1 
  106. to the segment address of the current block to calculate the 
  107. segment of the next MCB in the chain.
  108.  
  109.      The initial copy of COMMAND.COM creates a memory segment 
  110. which will contain the master environment. Usually, this is 
  111. located in the memory block directly after the one which contains 
  112. COMMAND.COM, and the environment pointer in COMMAND.COM's PSP is 
  113. set to 0. Beginning with MS-DOS version 3.3, however, the 
  114. location of the environment's memory block may be different. In 
  115. this case, the environment pointer in COMMAND.COM's PSP contains 
  116. the segment of the environment block.
  117.  
  118.      Once the memory block containing the environment is located, 
  119. we can directly manipulate the variables stored there. 
  120. Environment variables are stored in sequential order and are 
  121. terminated by NULs, exactly like strings in C. The end of the 
  122. valid data in the environment is indicated by a pair of 
  123. consecutive NULS. Each variable consists of a name (customarily 
  124. in upper case), and equal sign, and a text value.
  125.  
  126.      MSTR_ENV.C (listing 1) is a module for C which directly 
  127. accesses the master environment. It contains three public 
  128. functions, m_getenv(), m_putenv(), and m_delenv(). A fourth 
  129. function, m_findenv() initializes the pointer to the master 
  130. environment. Whenever one of the public functions is called, it 
  131. checks a flag (initialized) to see if it is necessary to call 
  132. m_findenv(). This eliminates the need for an explicit call by an 
  133. application program to an initialization function, making the 
  134. programmer's task easier and less error-prone.
  135.  
  136.      M_findenv() begins by invoking MS-DOS function 0x52. The 
  137. returned values in the ES and BX registers are then used to 
  138. construct a point to the segment address of the first MCB. The 
  139. first MCB is the one for the MS-DOS kernel and device drivers; 
  140. the second MCB is associated with COMMAND.COM. Using the formula 
  141. mentioned above for following the chain of MCBs, m_findenv() 
  142. finds the second MCB (for COMMAND.COM). That MCB contains the 
  143. segment of COMMAND.COM's PSP. Once the PSP has been located, the 
  144. environment pointer stored there is checked to see if it is 0. If 
  145. so, the environment is stored in the next consecutive memory 
  146. block above COMMAND.COM; otherwise, we have a segment address, 
  147. and can build a direct pointer to the master environment block. 
  148. Finally, m_findenv() calculates the size of the environment from 
  149. the size of its memory block.
  150.  
  151.      The three public functions make changes to the master 
  152. environment. Retrieving the value of a variable is done with the 
  153. m_getenv() function, which returns a pointer to a statically-
  154. allocated char array which contains the value of the requested 
  155. variable. The static array is changed every time that m_getenv() 
  156. is called. If it could not find the requested variable,  
  157. m_getenv() returns NULL.
  158.  
  159.      Deleting a variable is accomplished by calling m_delenv(), 
  160. passing it the name of the variable to be deleted. Caution should 
  161. be taken not to delete important MS-DOS environment variables 
  162. such as PATH or COMSPEC. A cautious programmer might add checks 
  163. in m_delenv() to prevent critical variables from being deleted. A 
  164. zero is returned to indicate success; a return of 1 reflects a 
  165. failure to find the variable.
  166.  
  167.      M_putenv() is used to store a new variable. It accepts the 
  168. name and value of the variable as parameters. It then calls 
  169. m_delenv() to delete any current variable of the same name, and 
  170. appends the new variable information to the end of the 
  171. environment. The name of the variable is converted to uppercase, 
  172. as this is the convention used by the internal MS-DOS commands 
  173. such as PATH and SET. If the new variable won't fit within the 
  174. available space in the environment, m_putenv() returns 1 to 
  175. indicate failure. Also, if the variable will be longer than 256 
  176. bytes, a 1 is returned. This is because the MS-DOS SET command 
  177. cannot manipulate environment variables which are longer than 256 
  178. bytes. A return value of 0 means that m_putenv() succeeded.
  179.  
  180.      MSTR_ENV.C is written in ANSI-conformant C, and has been 
  181. tested with Zortech C v1.07, Microsoft C v5.10, Microsoft Quick C 
  182. v2.0, WATCOM C v6.5, and Borland Turbo C v2.0. It should compile 
  183. and work under MS-DOS C compilers which support far pointers and 
  184. software interrupt calls. As with all functions which use 
  185. "undocumented features" of MS-DOS, it is important to realize 
  186. that these functions may not work with future versions of MS-DOS. 
  187. I made sure that the functions in MSTR_ENV.C worked with MS-DOS 
  188. versions 2.1, 3.0, 3.21, and 3.30.
  189.  
  190.      With care, however, it is possible to access the master 
  191. environment, giving the programmer a new resource for building 
  192. more capable programs.
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217.